home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 4: GNU Archives / Linux Cubed Series 4 - GNU Archives.iso / gnu / id-utils.2 / id-utils / id-utils-3.2 / src / fid.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-07  |  6.5 KB  |  285 lines

  1. /* fid.c -- list all tokens in the given file(s)
  2.    Copyright (C) 1986, 1995, 1996 Free Software Foundation, Inc.
  3.    Written by Greg McGary <gkm@gnu.ai.mit.edu>
  4.  
  5.    This program is free software; you can redistribute it and/or modify
  6.    it under the terms of the GNU General Public License as published by
  7.    the Free Software Foundation; either version 2, or (at your option)
  8.    any later version.
  9.  
  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.    GNU General Public License for more details.
  14.  
  15.    You should have received a copy of the GNU General Public License
  16.    along with this program; if not, write to the Free Software
  17.    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  18.  
  19. #include <config.h>
  20. #include <stdio.h>
  21. #include <getopt.h>
  22. #include "xstring.h"
  23. #include "xunistd.h"
  24. #include "xnls.h"
  25. #include "idfile.h"
  26. #include "error.h"
  27. #include "pathmax.h"
  28. #include "xmalloc.h"
  29. #include "xalloca.h"
  30.  
  31. int get_file_index __P((char *file_name));
  32. int is_hit __P((unsigned char const *hits, int file_number));
  33. int is_hit_1 __P((unsigned char const **hits, int level, int file_number));
  34. void skip_hits __P((unsigned char const **hits, int level));
  35. void usage __P((void));
  36.  
  37. struct idhead idh;
  38. int tree8_levels;
  39.  
  40. /* The name this program was run with. */
  41.  
  42. char const *program_name;
  43.  
  44. /* If nonzero, display usage information and exit.  */
  45.  
  46. static int show_help;
  47.  
  48. /* If nonzero, print the version on standard output then exit.  */
  49.  
  50. static int show_version;
  51.  
  52. /* The file name of the ID database.  */
  53.  
  54. struct file_link *cw_dlink;
  55. struct file_link **members_0;
  56. unsigned int bits_vec_size;
  57. char *hits_buf;
  58.  
  59. static struct option const long_options[] =
  60. {
  61.   { "file", required_argument, 0, 'f' },
  62.   { "help", no_argument, &show_help, 1 },
  63.   { "version", no_argument, &show_version, 1 },
  64.   { 0 }
  65. };
  66.  
  67. void
  68. usage (void)
  69. {
  70.   fprintf (stderr, _("Try `%s --help' for more information.\n"),
  71.        program_name);
  72.   exit (1);
  73. }
  74.  
  75. static void
  76. help_me (void)
  77. {
  78.   printf (_("\
  79. Usage: %s [OPTION] FILENAME [FILENAME2]\n\
  80. "), program_name);
  81.   printf (_("\
  82. List identifiers that occur in FILENAME, or if FILENAME2 is\n\
  83. also given list the identifiers that occur in both files.\n\
  84. \n\
  85.   -f, --file=FILE  file name of ID database\n\
  86.       --help       display this help and exit\n\
  87.       --version    output version information and exit\n\
  88. "));
  89.   exit (0);
  90. }
  91.  
  92. int
  93. main (int argc, char **argv)
  94. {
  95.   int index_1 = -1;
  96.   int index_2 = -1;
  97.  
  98.   program_name = argv[0];
  99.   idh.idh_file_name = 0;
  100.  
  101.   /* Set locale according to user's wishes.  */
  102.   setlocale (LC_ALL, "");
  103.  
  104.   /* Tell program which translations to use and where to find.  */
  105.   bindtextdomain (PACKAGE, LOCALEDIR);
  106.   textdomain (PACKAGE);
  107.  
  108.   for (;;)
  109.     {
  110.       int optc = getopt_long (argc, argv, "f:",
  111.                   long_options, (int *) 0);
  112.       if (optc < 0)
  113.     break;
  114.       switch (optc)
  115.     {
  116.     case 0:
  117.       break;
  118.  
  119.     case 'f':
  120.       idh.idh_file_name = optarg;
  121.       break;
  122.  
  123.     default:
  124.       usage ();
  125.     }
  126.     }
  127.  
  128.   if (show_version)
  129.     {
  130.       printf ("%s - %s\n", program_name, PACKAGE_VERSION);
  131.       exit (0);
  132.     }
  133.  
  134.   if (show_help)
  135.     help_me ();
  136.  
  137.   argc -= optind;
  138.   argv += optind;
  139.   if (argc < 1)
  140.     {
  141.       error (0, 0, _("no file name arguments"));
  142.       usage ();
  143.     }
  144.   if (argc > 2)
  145.     {
  146.       error (0, 0, _("too many file name arguments"));
  147.       usage ();
  148.     }
  149.  
  150.   /* Look for the ID database up the tree */
  151.   idh.idh_file_name = locate_id_file_name (idh.idh_file_name);
  152.   if (idh.idh_file_name == 0)
  153.     error (1, errno, _("can't locate `ID'"));
  154.  
  155.   init_idh_obstacks (&idh);
  156.   init_idh_tables (&idh);
  157.  
  158.   cw_dlink = get_current_dir_link ();
  159.  
  160.   /* Determine absolute name of the directory name to which database
  161.      constituent files are relative. */
  162.   members_0 = read_id_file (idh.idh_file_name, &idh);
  163.   bits_vec_size = (idh.idh_files + 7) / 4; /* more than enough */
  164.   tree8_levels = tree8_count_levels (idh.idh_files);
  165.  
  166.   index_1 = get_file_index ((argc--, *argv++));
  167.   if (argc)
  168.     index_2 = get_file_index ((argc--, *argv++));
  169.  
  170.   if (index_1 < 0)
  171.     return 1;
  172.  
  173.   hits_buf = xmalloc (idh.idh_buf_size);
  174.   fseek (idh.idh_FILE, idh.idh_tokens_offset, SEEK_SET);
  175.   {
  176.     int count = 0;
  177.     int i;
  178.     int separator = (isatty (STDOUT_FILENO) ? ' ' : '\n');
  179.     
  180.     for (i = 0; i < idh.idh_tokens; i++)
  181.       {
  182.     unsigned char const *hits;
  183.  
  184.     gets_past_00 (hits_buf, idh.idh_FILE);
  185.     hits = token_hits_addr (hits_buf);
  186.     if (is_hit (hits, index_1) && (index_2 < 0 || is_hit (hits, index_2)))
  187.       {
  188.         fputs (token_string (hits_buf), stdout);
  189.         putchar (separator);
  190.         count++;
  191.       }
  192.       }
  193.     if (count && separator == ' ')
  194.       putchar ('\n');
  195.   }
  196.  
  197.   return 0;
  198. }
  199.  
  200. int
  201. get_file_index (char *file_name)
  202. {
  203.   struct file_link **members;
  204.   struct file_link **end = &members_0[idh.idh_files];
  205.   struct file_link *fn_flink = 0;
  206.   char *file_name_buf = ALLOCA (char, PATH_MAX);
  207.   int has_slash = (strchr (file_name, '/') != 0);
  208.   int file_name_length = strlen (file_name);
  209.   int idx = -1;
  210.  
  211.   if (strstr (file_name, "./"))
  212.     fn_flink = parse_file_name (file_name, cw_dlink);
  213.  
  214.   for (members = members_0; members < end; members++)
  215.     {
  216.       struct file_link *flink = *members;
  217.       if (fn_flink)
  218.     {
  219.       if (fn_flink != flink)
  220.         continue;
  221.     }
  222.       else if (has_slash)
  223.     {
  224.       int member_length;
  225.       maybe_relative_file_name (file_name_buf, flink, cw_dlink);
  226.       member_length = strlen (file_name_buf);
  227.       if (file_name_length > member_length
  228.           || !strequ (&file_name_buf[member_length - file_name_length], file_name))
  229.         continue;
  230.     }
  231.       else if (!strequ (flink->fl_name, file_name))
  232.     continue;
  233.       if (idx >= 0)
  234.     {
  235.       error (0, 0, _("`%s' is ambiguous"), file_name);
  236.       return -1;
  237.     }
  238.       idx = members - members_0;
  239.     }
  240.   if (idx < 0)
  241.     error (0, 0, _("`%s' not found"), file_name);
  242.   return idx;
  243. }
  244.  
  245. int
  246. is_hit (unsigned char const *hits, int file_number)
  247. {
  248.   return is_hit_1 (&hits, tree8_levels, file_number);
  249. }
  250.  
  251. int
  252. is_hit_1 (unsigned char const **hits, int level, int file_number)
  253. {
  254.   int file_hit = 1 << ((file_number >> (3 * --level)) & 7);
  255.   int hit = *(*hits)++;
  256.   int bit;
  257.  
  258.   if (!(file_hit & hit))
  259.     return 0;
  260.   if (level == 0)
  261.     return 1;
  262.  
  263.   for (bit = 1; (bit < file_hit) && (bit & 0xff); bit <<= 1)
  264.     {
  265.       if (hit & bit)
  266.     skip_hits (hits, level);
  267.     }
  268.   return is_hit_1 (hits, level, file_number);
  269. }
  270.  
  271. void
  272. skip_hits (unsigned char const **hits, int level)
  273. {
  274.   int hit = *(*hits)++;
  275.   int bit;
  276.  
  277.   if (--level == 0)
  278.     return;
  279.   for (bit = 1; bit & 0xff; bit <<= 1)
  280.     {
  281.       if (hit & bit)
  282.     skip_hits (hits, level);
  283.     }
  284. }
  285.